<template>
  <div class="tree-container">
    <!-- Null 值 -->
    <div v-if="data === null" class="node-container" :data-type="'null'">
      <div class="node-header" @click="toggleExpanded">
        <button v-if="hasChildren(data)" class="node-toggle" @click.stop="toggleExpanded">
          <i class="fas" :class="isExpanded ? 'fa-minus-square' : 'fa-plus-square'"></i>
        </button>
        <span class="node-type null">null</span>
        <span v-if="!isEditing" class="node-value" @click="startEditing">{{ formatValue(data) }}</span>
        <input 
          v-else
          ref="inputRef"
          v-model="editValue"
          class="node-input"
          @blur="saveEdit"
          @keydown.enter="saveEdit"
          @keydown.escape="cancelEdit"
          @input="handleInputChange">
      </div>
    </div>
    
    <!-- 基本类型（字符串、数字、布尔值） -->
    <div v-else-if="typeof data !== 'object'" class="node-container" :data-type="typeof data">
      <div class="node-header" @click="toggleExpanded">
        <button v-if="hasChildren(data)" class="node-toggle" @click.stop="toggleExpanded">
          <i class="fas" :class="isExpanded ? 'fa-minus-square' : 'fa-plus-square'"></i>
        </button>
        <span class="node-type" :class="typeof data">{{ typeof data }}</span>
        <span v-if="!isEditing" class="node-value" @click="startEditing">{{ formatValue(data) }}</span>
        <input 
          v-else
          ref="inputRef"
          v-model="editValue"
          class="node-input"
          @blur="saveEdit"
          @keydown.enter="saveEdit"
          @keydown.escape="cancelEdit"
          @input="handleInputChange">
      </div>
    </div>
    
    <!-- 数组 -->
    <div v-else-if="Array.isArray(data)" class="node-container" data-type="array">
      <div class="node-header" @click="toggleExpanded">
        <button class="node-toggle" @click.stop="toggleExpanded">
          <i class="fas" :class="isExpanded ? 'fa-minus-square' : 'fa-plus-square'"></i>
        </button>
        <span class="node-type array">array</span>
        <span class="node-value">[{{ data.length }}]</span>

      </div>
      
      <div class="node-children" v-show="isExpanded">
        <div v-for="(item, index) in data" :key="index" class="node-line">
          <button class="child-toggle" v-if="hasChildren(item)" @click="toggleChildExpanded(index)">
            <i class="fas" :class="getChildExpandedIcon(index)"></i>
          </button>
          <span class="node-key">[{{ index }}]:</span>
          <json-tree 
            :data="item" 
            :expanded="isChildExpanded(index)"
            @update="handleChildUpdate(index, $event)"></json-tree>
        </div>
      </div>
    </div>
    
    <!-- 对象 -->
    <div v-else class="node-container" data-type="object">
      <div class="node-header" @click="toggleExpanded">
        <button class="node-toggle" @click.stop="toggleExpanded">
          <i class="fas" :class="isExpanded ? 'fa-minus-square' : 'fa-plus-square'"></i>
        </button>
        <span class="node-type object">object</span>
        <span class="node-value">{{ Object.keys(data).length }} 个属性</span>
      </div>
      
      <div class="node-children" v-show="isExpanded">
        <div v-for="([key, value]) in Object.entries(data)" :key="key" class="node-line">
          <button class="child-toggle" v-if="hasChildren(value)" @click="toggleChildExpanded(key)">
            <i class="fas" :class="getChildExpandedIcon(key)"></i>
          </button>
          <span class="node-key">"{{ key }}":</span>
          <json-tree 
            :data="value" 
            :expanded="isChildExpanded(key)"
            @update="handleChildUpdate(key, $event)"></json-tree>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'JsonTree',
  props: {
    data: {
      required: true
    },
    expanded: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      isExpanded: this.expanded,
      isEditing: false,
      editValue: '',
      originalValue: null,
      childExpandedStates: new Map()
    }
  },
  watch: {
    expanded(newVal) {
      this.isExpanded = newVal
      // 同步所有子类的展开状态
      this.syncAllChildrenExpandedState(newVal)
    }
  },
  methods: {
    toggleExpanded() {
      this.isExpanded = !this.isExpanded
    },
    startEditing() {
      if (typeof this.data === 'object' && this.data !== null) return
      
      this.isEditing = true
      this.editValue = this.formatValue(this.data, true)
      this.originalValue = this.data
      
      this.$nextTick(() => {
        if (this.$refs.inputRef) {
          this.$refs.inputRef.focus()
          this.$refs.inputRef.select()
        }
      })
    },
    saveEdit() {
      if (!this.isEditing) return
      
      try {
        const newValue = this.parseValue(this.editValue, typeof this.data)
        this.$emit('update', newValue)
        this.isEditing = false
      } catch (error) {
        console.error('编辑值失败:', error)
        this.cancelEdit()
      }
    },
    cancelEdit() {
      this.isEditing = false
      this.editValue = ''
      this.originalValue = null
    },
    formatValue(value, forInput = false) {
      if (value === null) return 'null'
      if (typeof value === 'string') return forInput ? value : `"${value}"`
      if (typeof value === 'boolean') return value.toString()
      if (typeof value === 'number') {
        if (Math.abs(value) > 999999999999) {
          return value.toString()
        }
        return value.toString()
      }
      return String(value)
    },
    parseValue(input, originalType) {
      if (originalType === 'string') {
        return input
      }
      if (originalType === 'number') {
        const num = parseFloat(input)
        if (isNaN(num)) throw new Error('不是有效的数字')
        return num
      }
      if (originalType === 'boolean') {
        if (input.toLowerCase() === 'true') return true
        if (input.toLowerCase() === 'false') return false
        throw new Error('必须是 true 或 false')
      }
      if (originalType === 'null') {
        if (input.toLowerCase() === 'null') return null
        throw new Error('必须是 null')
      }
      return input
    },

    handleChildUpdate(key, newValue) {
      const newData = Array.isArray(this.data) 
        ? [...this.data] 
        : {...this.data}
      
      newData[key] = newValue
      this.$emit('update', newData)
    },
    hasChildren(value) {
      return value && typeof value === 'object' && value !== null && 
             ((Array.isArray(value) && value.length > 0) || 
              (Object.keys(value).length > 0))
    },
    toggleChildExpanded(key) {
      const currentState = this.childExpandedStates.get(key)
      // 如果当前状态是undefined，使用父节点的展开状态作为初始值
      const initialState = currentState === undefined ? this.isExpanded : currentState
      this.childExpandedStates.set(key, !initialState)
    },
    isChildExpanded(key) {
      const state = this.childExpandedStates.get(key)
      return state === undefined ? this.isExpanded : state
    },
    getChildExpandedIcon(key) {
      return this.isChildExpanded(key) ? 'fa-minus-square' : 'fa-plus-square'
    },
    // 同步所有子类的展开状态
    syncAllChildrenExpandedState(expanded) {
      const keys = Array.from(this.childExpandedStates.keys())
      keys.forEach(key => {
        this.childExpandedStates.set(key, expanded)
      })
    },
    handleInputChange() {
      // 实时同步更新数据
      try {
        const newValue = this.parseValue(this.editValue, typeof this.data)
        this.$emit('update', newValue)
      } catch (error) {
        // 输入无效时保持原值
        console.error('输入值无效:', error)
      }
    }
  }
}
</script>

<style scoped>
.tree-container {
  font-family: 'Fira Code', 'Consolas', 'Monaco', 'Cascadia Code', monospace;
  font-size: 14px;
  line-height: 1.5;
  color: #1e293b;
  font-feature-settings: "liga" 1, "calt" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.node-container {
  margin-bottom: 2px;
  position: relative;
  transition: all 0.2s ease;
}

.node-container:hover {
  z-index: 2;
}

.node-header {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 6px;
  transition: all 0.2s ease;
  background: transparent;
  gap: 4px;
  min-height: 24px;
  border: 1px solid transparent;
  flex-wrap: nowrap;
  overflow: hidden;
  line-height: 1.5;
}



.node-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: #94a3b8;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  transition: all 0.2s ease;
  border-radius: 2px;
  flex-shrink: 0;
  margin-right: 2px;
}



/* 确保Font Awesome图标正确显示 */
.node-toggle .fas {
  font-size: 12px;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.child-toggle .fas {
  font-size: 10px;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.node-type {
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  border: 1px solid;
  flex-shrink: 0;
  white-space: nowrap;
  margin-right: 2px;
  line-height: 1.2;
  vertical-align: middle;
}

.node-type.string {
  background: rgba(219, 234, 254, 0.8);
  color: #1e40af;
  border-color: rgba(59, 130, 246, 0.3);
}

.node-type.number {
  background: rgba(220, 252, 231, 0.8);
  color: #166534;
  border-color: rgba(34, 197, 94, 0.3);
}

.node-type.boolean {
  background: rgba(243, 232, 255, 0.8);
  color: #7e22ce;
  border-color: rgba(168, 85, 247, 0.3);
}

.node-type.null {
  background: rgba(248, 250, 252, 0.8);
  color: #64748b;
  border-color: rgba(100, 116, 139, 0.3);
}

.node-type.object {
  background: rgba(254, 249, 195, 0.8);
  color: #854d0e;
  border-color: rgba(202, 138, 4, 0.3);
}

.node-type.array {
  background: rgba(255, 237, 213, 0.8);
  color: #9a3412;
  border-color: rgba(249, 115, 22, 0.3);
}

.node-key {
  color: #3b82f6;
  font-weight: 600;
  font-size: 12px;
  white-space: nowrap;
  flex-shrink: 0;
  margin-right: 2px;
  line-height: 1.5;
  vertical-align: middle;
}

.node-value {
  color: #1e293b;
  font-weight: 500;
  padding: 1px 4px;
  border-radius: 3px;
  cursor: text;
  transition: all 0.2s ease;
  background: transparent;
  border: 1px solid transparent;
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 12px;
  margin-left: 2px;
  line-height: 1.5;
  vertical-align: middle;
}





.node-children {
  margin-left: 20px;
  padding-left: 12px;
  border-left: 2px solid #e2e8f0;
  margin-top: 4px;
  position: relative;
  transition: all 0.3s ease;
}

.node-children::before {
  content: '';
  position: absolute;
  left: -2px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(to bottom, transparent 0%, #e2e8f0 10%, #e2e8f0 90%, transparent 100%);
}

.node-line {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 2px;
  padding: 1px 0;
  position: relative;
  transition: all 0.2s ease;
  flex-wrap: nowrap;
  min-height: 20px;
  line-height: 1.5;
}



.node-line .node-key {
  flex-shrink: 0;
  margin-right: 0;
}

.child-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: #cbd5e1;
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  transition: all 0.2s ease;
  border-radius: 2px;
  margin-right: 1px;
  margin-top: 1px;
  flex-shrink: 0;
}



.child-toggle .fas {
  font-size: 9px;
}

.node-input {
  width: auto;
  min-width: 120px;
  max-width: 300px;
  padding: 3px 8px;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  font-family: inherit;
  font-size: 13px;
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  line-height: 1.3;
  transition: all 0.2s ease;
}

.node-input:focus {
  outline: none;
  border-color: #3b82f6;
}

/* 优化基本类型值的显示 */
.node-container[data-type="string"] .node-value {
  color: #dc2626;
  font-weight: 600;
}

.node-container[data-type="number"] .node-value {
  color: #059669;
  font-weight: 700;
}

.node-container[data-type="boolean"] .node-value {
  color: #7c3aed;
  font-weight: 700;
}

.node-container[data-type="null"] .node-value {
  color: #6b7280;
  font-weight: 600;
}

/* 动画效果 */
.node-children {
  animation: slideDown 0.3s ease-out;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 响应式调整 */
@media (max-width: 768px) {
  .tree-container {
    font-size: 13px;
  }
  
  .node-header {
    padding: 4px 6px;
    min-height: 24px;
    gap: 4px;
  }
  
  .node-type {
    font-size: 10px;
    padding: 1px 6px;
  }
  
  .node-key {
    font-size: 12px;
  }
  
  .node-value {
    font-size: 12px;
    padding: 1px 4px;
  }
  
  .node-children {
    margin-left: 16px;
    padding-left: 8px;
  }
  
  .node-line {
    gap: 4px;
  }
}
</style>